import type { AxiosRequestConfig, AxiosResponse } from 'axios'
import axios, { CanceledError } from 'axios'
import { isString } from 'lodash-es'
import qs from 'qs'
import { message as $message, Modal } from 'ant-design-vue'
import { ResultEnum } from '@/enums/httpEnum'
import { useUserStore } from '@/store/modules/user'
import { useSSEStore } from '@/store/modules/sse'
import { toggleDomainNames, useI18n } from '@/hooks/useI18n'
import { useLocaleStoreWithOut } from '@/store/modules/locale'


const { getLocale } = useLocaleStoreWithOut()

export interface RequestOptions extends AxiosRequestConfig {
  /** 是否直接将数据从响应中提取出，例如直接返回 res.data，而忽略 res.code 等信息 */
  isReturnResult?: boolean;
  /** 请求成功是提示信息 */
  successMsg?: string;
  /** 请求失败是提示信息 */
  errorMsg?: string;
  /** 成功时，是否显示后端返回的成功信息 */
  showSuccessMsg?: boolean;
  /** 失败时，是否显示后端返回的失败信息 */
  showErrorMsg?: boolean;
  requestType?: 'json' | 'form';
}

const UNKNOWN_ERROR: string = useI18n().t('common.error.none')

let hasShownAuthError: boolean = false // 全局变量，用于跟踪是否已显示认证错误

/** 真实请求的路径前缀 */
export const baseApiUrl = toggleDomainNames(getLocale)
/** mock请求路径前缀 */
// const baseMockUrl = import.meta.env.VITE_MOCK_API;
const controller = new AbortController()
const service = axios.create({
  baseURL: baseApiUrl,
  // adapter: 'fetch',
  timeout: 10000,
  signal: controller.signal,
  paramsSerializer(params) {
    return qs.stringify(params, { arrayFormat: 'brackets' })
  }
})

service.interceptors.request.use(
  (config) => {
    const userStore = useUserStore()

    const token = userStore.token
    if (token && config.headers) {
      // 请求头token信息，请根据实际情况进行修改
      config.headers['Authorization'] = `Bearer ${token}`
    }
    return config
  },
  (error) => {
    return Promise.reject(error)
  }
)

service.interceptors.response.use(
  (response: AxiosResponse<BaseResponse>) => {
    const { t } = useI18n()
    const res = response.data
    const msgInfo = res.msg || res.message || UNKNOWN_ERROR

    // if(response.request.responseType === 'blob'){
    //   return response
    // }

    if (res.code !== ResultEnum.SUCCESS) {
      $message.error(msgInfo)
      // Illegal token
      if ([401].includes(res.code)) {
        // hasShownAuthError = true // 更新状态为已显示
        // to re-login
        Modal.confirm({
          title: t('common.request.logintime'),
          content: res.msg || t('common.request.logintime'),
          okText: t('common.request.relanding'),
          cancelText: t('common.cancelText'),
          onOk: () => {
            localStorage.clear()
            window.location.reload()
          }
        })
        // nextTick(() => {
        //   localStorage.clear()
        //   window.location.reload()
        // })
      }

      // Illegal token
      if ([1001].includes(res.code) && !hasShownAuthError) {
        hasShownAuthError = true // 更新状态为已显示
        // to re-login
        Modal.confirm({
          title: t('common.request.logintime'),
          content: res.msg || t('common.request.logintime'),
          okText: t('common.request.relanding'),
          cancelText: t('common.cancelText'),
          onOk: () => {
            localStorage.clear()
            window.location.reload()
          }
        })
      }

      // throw other
      const error = new Error(msgInfo) as Error & { code: any }
      error.code = res.code
      return Promise.reject(error)
    } else {
      const sseStore = useSSEStore()
      sseStore.setServerConnectStatus(true)
      return response
    }
  },
  (error) => {
    if (!(error instanceof CanceledError)) {
      // 处理 422 或者 500 的错误异常提示
      const errMsg = error?.response?.data?.msg ?? UNKNOWN_ERROR
      $message.error({ content: errMsg, key: errMsg })
      error.msg = errMsg
    }
    return Promise.reject(error)
  }
)

type BaseResponse<T = any> = Omit<API.ResOp, 'data'> & {
  data: T;
};

export function request<T = any>(
  url: string,
  config: { isReturnResult: false } & RequestOptions
): Promise<BaseResponse<T>>;
export function request<T = any>(
  url: string,
  config: RequestOptions
): Promise<BaseResponse<T>['data']>;
export function request<T = any>(
  config: { isReturnResult: false } & RequestOptions
): Promise<BaseResponse<T>>;
export function request<T = any>(config: RequestOptions): Promise<BaseResponse<T>['data']>;
/**
 *
 * @param _url - request url
 * @param _config - AxiosRequestConfig
 */
export async function request(_url: string | RequestOptions, _config: RequestOptions = {}) {
  const url = isString(_url) ? _url : _url.url
  const config = isString(_url) ? _config : _url
  try {
    // 兼容 from data 文件上传的情况
    const { requestType, isReturnResult = true, ...rest } = config

    const response = (await service.request({
      url,
      ...rest,
      headers: {
        ...rest.headers,
        ...(requestType === 'form' ? { 'Content-Type': 'multipart/form-data' } : {})
      }
    })) as AxiosResponse<BaseResponse>

    const { data } = response
    const { code, message } = data || {}

    const hasSuccess = data && Reflect.has(data, 'code') && code === ResultEnum.SUCCESS

    if (hasSuccess) {
      const { successMsg, showSuccessMsg } = config
      if (successMsg) {
        $message.success(successMsg)
      } else if (showSuccessMsg && message) {
        $message.success(message)
      }
    }

    // 页面代码需要获取 code，data，msg 等信息时，需要将 isReturnResult 设置为 false
    if (!isReturnResult) {
      return data
    } else {
      return data.data
    }
  } catch (error: any) {

    return Promise.reject(error)
  }
}
